package com.tianji.learning.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.trade.OrderBasicDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.AssertUtils;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.entity.LearningLesson;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.pojo.LearningPlanDTO;
import com.tianji.learning.pojo.LearningPlanPageVO;
import com.tianji.learning.pojo.LearningPlanVO;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.tianji.learning.vo.LearningLessonVO;
import com.tianji.learning.vo.LessonStatus;
import com.tianji.learning.vo.PlanStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author xjs
 */
@Slf4j
@Service
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {


    /**
     * 课程服务的client
     * */
    @Autowired
    private CourseClient courseClient;

    /**
     * 目录client
     * */
    @Autowired
    private CatalogueClient catalogueClient;

    @Autowired
    private ILearningRecordService recordService;

    @Override
    public void setPlans(LearningPlanDTO dto) {
        // 获取userId
        Long userId = UserContext.getUser();
        LearningLessonVO lessonDB = this.getLessonByUserIdCourseId(userId, dto.getCourseId());
        AssertUtils.isNotNull(lessonDB, "查询不到课程信息");
        // 更新学习计划
        LearningLesson lessonUpdate = new LearningLesson();
        lessonUpdate.setId(lessonDB.getId());
        lessonUpdate.setWeekFreq(dto.getFreq());
        if(Objects.equals(lessonDB.getPlanStatus(), PlanStatus.NO_PLAN)){
            lessonUpdate.setPlanStatus(PlanStatus.PLAN_RUNNING.getValue());
        }
        this.updateById(lessonUpdate);
    }

    @Override
    public LearningPlanPageVO getPlans(PageQuery pageQuery) {
        // 获取userId
        Long userId = UserContext.getUser();
        // 先查lesson表，查询总的计划学习的小节的数量
        int weekTotalPlan = this.baseMapper.sumWeekFreqByUserId(userId);
        // 再查record表，查询实际学完的小节的数量
        LocalDate now = LocalDate.now();
        LocalDateTime weekBeginTime = DateUtils.getWeekBeginTime(now);
        LocalDateTime weekEndTime = DateUtils.getWeekEndTime(now);
        int weekFinished = recordService.getLearnedSectionCountByUserIdFinishTime(userId, null, weekBeginTime, weekEndTime);
        // 分页查询，根据用户的课做分页
        // 分页条件
        IPage<LearningLesson> ipage =pageQuery.toMpPage("latest_learn_time", false);
        // 查询条件
        LambdaQueryWrapper<LearningLesson> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LearningLesson::getUserId, userId);
        // 分页查询
        IPage<LearningLesson> page = this.page(ipage, queryWrapper);
        // 得到当前页数据列表
        List<LearningLesson> records = page.getRecords();
        List<LearningPlanVO> voList = new ArrayList<>();
        // 如果数据不是空，转化成前端需要的vo对象
        if(!CollectionUtils.isEmpty(records)){
            // 遍历Lesson转化成前端需要的vo
            for (LearningLesson lesson : records) {
                CourseFullInfoDTO course = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
                AssertUtils.isNotNull(course, "查询不到课程信息");
                // 总的小节数量
                Integer sectionNum = course.getSectionNum();
                // 课程名称
                String name = course.getName();
                // 查询本周实际学习的当前课程的小节的数量
                int weekLearnedSections = recordService.getLearnedSectionCountByUserIdFinishTime(userId, lesson.getId(), weekBeginTime, weekEndTime);
                // 构造VO对象
                LearningPlanVO vo = new LearningPlanVO();
                // 课程明
                vo.setCourseName(name);
                // 课程id
                vo.setCourseId(lesson.getCourseId());
                // 每周计划学习的小节数量
                vo.setWeekFreq(lesson.getWeekFreq());
                // 每周实际学习的小节数量
                vo.setWeekLearnedSections(weekLearnedSections);
                // 最近学习时间
                vo.setLatestLearnTime(lesson.getLatestLearnTime());
                // 总已学习章节数
                vo.setLearnedSections(lesson.getLearnedSections());
                // 课程章节数量
                vo.setSections(sectionNum);
                voList.add(vo);
            }
        }
        // 返回结果
        LearningPlanPageVO vo = new LearningPlanPageVO();
        vo.setWeekFinished(weekFinished);
        vo.setWeekTotalPlan(weekTotalPlan);
        vo.setList(voList);
        return vo;
    }


    @Override
    public LearningLessonVO getLessonByUserIdCourseId(Long userId, Long courseId) {
        LearningLesson lesson = getOne(buildUserIdAndCourseIdWrapper(userId, courseId));
        if (lesson == null) {
            return null;
        }
        return BeanUtils.copyBean(lesson, LearningLessonVO.class);
    }

    @Override
    public void deleteCourseFromLesson(Long userId, Long courseId) {
        // 1.获取当前登录用户
        if (userId == null) {
            userId = UserContext.getUser();
        }
        // 2.删除课程
        remove(buildUserIdAndCourseIdWrapper(userId, courseId));
    }

    @Override
    public Integer countLearningLessonByCourse(Long courseId) {
        // select count(1) from xx where course_id = #{cc} AND status in (0, 1, 2)
        return lambdaQuery()
                .eq(LearningLesson::getCourseId, courseId)
                .in(LearningLesson::getStatus,
                        LessonStatus.NOT_BEGIN.getValue(),
                        LessonStatus.LEARNING.getValue(),
                        LessonStatus.FINISHED.getValue())
                .count();
    }

    @Override
    public Long isLessonValid(Long courseId) {
        // 1.获取登录用户
        Long userId = UserContext.getUser();
        if (userId == null) {
            return null;
        }
        // 2.查询课程
        LearningLesson lesson = getOne(buildUserIdAndCourseIdWrapper(userId, courseId));
        if (lesson == null) {
            return null;
        }
        return lesson.getId();
    }

    @Override
    public LearningLessonVO now() {
        // 获取当前登录的userId
        Long userId = UserContext.getUser();
        // 查询课表，当前正在学习的课程
        // 根据最近学习的时间倒序查询第一条
        LambdaQueryWrapper<LearningLesson> queryWrapper = new LambdaQueryWrapper<>();
        // 查询条件
        queryWrapper.eq(LearningLesson::getUserId, userId);
        queryWrapper.eq(LearningLesson::getStatus, LessonStatus.LEARNING.getValue());
        // 倒序
        queryWrapper.orderByDesc(LearningLesson::getLatestLearnTime);
        // 在sql语句的最后，做拼接
        queryWrapper.last(" limit 1");
        // 查询数据库
        LearningLesson lesson = this.getOne(queryWrapper);
        if(lesson == null){
            return null;
        }
        // 查询总的课程数量
        LambdaQueryWrapper<LearningLesson> countWrapper = new LambdaQueryWrapper<>();
        countWrapper.eq(LearningLesson::getUserId, userId);
        int count = this.count(countWrapper);

        // 远程查询course服务，得到course信息，填充课程和章节的信息
        List<Long> courseIds = Arrays.asList(lesson.getCourseId());
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        if(CollectionUtils.isEmpty(courseList)){
            log.error("根据courseId查询不到course信息，courseIds：{}", courseIds);
            throw new BizIllegalException("网络异常，请稍后重试");
        }
        CourseSimpleInfoDTO course = courseList.get(0);

        // 远程查询目录信息
        List<CataSimpleInfoDTO> catalogueList = catalogueClient.batchQueryCatalogue(Arrays.asList(lesson.getLatestSectionId()));
        if(CollectionUtils.isEmpty(catalogueList)){
            log.error("根据SectionId查询不到章节信息，sectionId：{}", lesson.getLatestSectionId());
            throw new BizIllegalException("网络异常，请稍后重试");
        }
        CataSimpleInfoDTO section = catalogueList.get(0);
        // 把LearningLesson转化成vo
        LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);
        vo.setCourseAmount(count);
        // 名称、小节数量、封面来自course
        vo.setCourseName(course.getName());
        vo.setSections(course.getSectionNum());
        vo.setCourseCoverUrl(course.getCoverUrl());
        // 目录的名称、index来自于catalogue
        vo.setLatestSectionName(section.getName());
        vo.setLatestSectionIndex(section.getCIndex());
        return vo;
    }

    @Override
    public PageDTO<LearningLessonVO> pageQuery(PageQuery query) {
        // 获取当前用户id
        Long userId = UserContext.getUser();
        // 分页查询我的课表
        LambdaQueryWrapper<LearningLesson> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LearningLesson::getUserId, userId);
        //分页查询
        Page<LearningLesson> page = this.page(query.toMpPage(query.getSortBy(), query.getIsAsc()), queryWrapper);
        // 当前页数据列表
        List<LearningLesson> records = page.getRecords();
        // 如果当前页数据为空，返回空的PageDTO
        if(CollectionUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }
        // 远程查询course服务，得到course信息，填充课程和章节的信息
        List<Long> courseIds = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toList());
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        if(CollectionUtils.isEmpty(courseList)){
            log.error("根据courseId查询不到course信息，courseIds：{}", courseIds);
            throw new BizIllegalException("网络异常，请稍后重试");
        }
        // 把LearningLesson转化LearningLessonVO
        List<LearningLessonVO> voList = new ArrayList<>();
        for (LearningLesson record : records) {
            LearningLessonVO vo = BeanUtils.copyBean(record, LearningLessonVO.class);
            CourseSimpleInfoDTO course = findByCourseId(courseList, record.getCourseId());
            if(course == null){
                log.error("根据courseId查询不到course信息，courseId：{}", record.getCourseId());
                throw new BizIllegalException("网络异常，请稍后重试");
            }
            // 课程名、封面、章节数量来自course服务
            vo.setCourseName(course.getName());
            vo.setCourseCoverUrl(course.getCoverUrl());
            vo.setSections(course.getSectionNum());
            voList.add(vo);
        }
        // 返回
        return PageDTO.of(page, voList);
    }

    @Override
    public void onOrderPaySuccess(OrderBasicDTO dto) {
        // 合法性校验
        List<Long> courseIds = dto.getCourseIds();
        Long userId = dto.getUserId();
        if(CollectionUtils.isEmpty(courseIds ) ||  userId == null){
            log.error("支付完成的消息异常：{}", JSON.toJSONString(dto));
            return;
        }
        // 远程调用course服务查询course信息
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        if(CollectionUtils.isEmpty(courseList)){
            log.error("调用course服务查询course信息为空，courseIds：{}", courseIds);
            return;
        }
        List<LearningLesson> lessons = new ArrayList<>();
        //遍历courseIds
        for (Long courseId : courseIds) {
            LearningLesson lesson = new LearningLesson();
            lesson.setUserId(userId);
            lesson.setCourseId(courseId);
            lesson.setCreateTime(LocalDateTime.now());
            lesson.setUpdateTime(LocalDateTime.now());
            // 过期时间
            CourseSimpleInfoDTO courseDTO = findByCourseId(courseList,courseId);
            if(courseDTO == null){
                // 说明课程不存在
                log.error("调用course服务查询course信息为空，courseId：{}", courseId);
                return;
            }else{
                // 有效期，month
                Integer validDuration = courseDTO.getValidDuration();
                if(validDuration == null || validDuration <= 0){
                    // 不过期
                }else{
                    // 当前时间+有效的月数
                    lesson.setExpireTime(LocalDateTime.now().plusMonths(validDuration));
                }
            }
            lessons.add(lesson);
        }
        // 批量保存
        this.saveBatch(lessons);
    }

    private CourseSimpleInfoDTO findByCourseId(List<CourseSimpleInfoDTO> courseList, Long courseId) {
        Optional<CourseSimpleInfoDTO> any = courseList.stream().filter(c -> Objects.equals(c.getId(), courseId)).findAny();
        if(any.isPresent()){
            return any.get();
        }
        return null;
    }

    private LambdaQueryWrapper<LearningLesson> buildUserIdAndCourseIdWrapper(Long userId, Long courseId) {
        LambdaQueryWrapper<LearningLesson> queryWrapper = new QueryWrapper<LearningLesson>()
                .lambda()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId);
        return queryWrapper;
    }
}
